////////////////////////////////////////////////////////////////////////////////
//
//  FLEX USER GROUP HOKURIKU
//  Copyright 2009 Flex User Group Hokuriku
//  All Rights Reserved.
// 
//  NOTICE: Flex User Group Hokuriku permits you to use, 
//  modify, and distribute this file 
//  in accordance with the terms of the license agreement accompanying it.
//
////////////////////////////////////////////////////////////////////////////////
package net.fxug.hokuriku.chocolat.view
{
	import flash.display.Bitmap;
	import flash.display.BlendMode;
	import flash.display.NativeWindow;
	import flash.display.NativeWindowInitOptions;
	import flash.display.NativeWindowSystemChrome;
	import flash.display.NativeWindowType;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.DropShadowFilter;
	import flash.geom.Matrix;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.text.TextField;
	import flash.text.TextFormat;
	
	import mx.logging.ILogger;
	
	import net.fxug.hokuriku.chocolat.utils.LoggingUtil;
	
	/**
	 * 通知ウィンドウクラス
	 *
	 * @author shoito
	 */
	public class NotificationWindow extends NativeWindow
	{
		private static const GOOD_BAD_WIDTH:int = 52;
		private static const ICON_SIZE:int = 32;
		private static const COMMENT_WIDTH:int = 260;
		private static const WIDTH:int = 320;
		private static const HEIGHT:int = 64;
		private static const MIN_HEIGHT:int = 64;
		private static const MAX_HEIGHT:int = 96;
		private static const VERTICAL_GUTTER:int = 5;
		private static const HORIZONTAL_GUTTER:int = 10;
		private static const ROUND:int = 20;
		
		private static const GOOD_COLOR:uint = 0x00BB00;
		private static const BAD_COLOR:uint = 0xBB0000;
		
		private static var logger:ILogger = LoggingUtil.getLogger(NotificationWindow);
		
		private const userNameFormatter:TextFormat = new TextFormat("arial", 12, 0xe4e4e4);
		private const commentFormatter:TextFormat = new TextFormat("arial", 18, 0xe4e4e4);
		
		/**
		 * 通知ウィンドウの表示時間(min)
		 */
		public var timeToLive:uint;
		
		/**
		 * 通知ウィンドウのマネージャーインスタンス
		 */
		private var manager:NotificationManager;
		
		[Embed(source='/assets/images/good_hand.png')]
		private var Good:Class;
		
		[Embed(source='/assets/images/bad_hand.png')]
		private var Bad:Class;
		
		/**
		 * 通知の種類(good, bad)
		 */
		private var notifyType:String;
		
		/**
		 * 通知ウィンドウコンストラクタ
		 *
		 * @param manager NotificationManager
		 * @param notifyType 通知種類(good, bad)
		 * @param comment コメント
		 * @param userName 送信者名
		 * @param link 関連リンク情報
		 */
		public function NotificationWindow(manager:NotificationManager, notifyType:String = NotificationManager.NOTIFY_GOOD, comment:String = "", userName:String = "", link:String = null):void
		{
			this.manager = manager;
			this.notifyType = notifyType;
			
			var options:NativeWindowInitOptions = new NativeWindowInitOptions();
			options.type = NativeWindowType.LIGHTWEIGHT;
			options.systemChrome = NativeWindowSystemChrome.NONE;
			options.transparent = true;
			super(options);
			
			initializeContents(notifyType, comment, userName, link);
		}
		
		private function initializeContents(notifyType:String, comment:String, userName:String, link:String):void
		{
			this.alwaysInFront = true;
			this.width = GOOD_BAD_WIDTH;
			this.height = HEIGHT;
			
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN, function(mouseEvent:MouseEvent):void
			{
				clickHandler(mouseEvent, link);
			});
			this.stage.align = StageAlign.TOP_LEFT;
			this.stage.scaleMode = StageScaleMode.NO_SCALE;
			
			this.manager.addEventListener(NotificationManager.LIFE_TICK_EVENT, this.lifeTick, false, 0, true);
			
			var IconClass:Class = (notifyType == NotificationManager.NOTIFY_GOOD) ? Good : Bad;
			addIcon(IconClass);
			addUser(userName);
			addComment(comment);
			
			drawBackground(notifyType);
		}
		
		private function addIcon(IconClass:Class):void
		{
			var icon:Sprite = getIcon(IconClass);
			this.stage.addChild(icon);
			icon.x = HORIZONTAL_GUTTER;
			icon.y = VERTICAL_GUTTER + 15;
		}
		
		private function addUser(userName:String):void
		{
			var userText:TextField = new TextField();
			userText.text = userName;
			userText.wordWrap = true;
			userText.setTextFormat(userNameFormatter);
			this.stage.addChild(userText);
			userText.x = HORIZONTAL_GUTTER;
			userText.y = VERTICAL_GUTTER;
		}
		
		private function addComment(comment:String):void
		{
			var commentText:TextField = new TextField();
			commentText.text = comment;
			commentText.wordWrap = true;
			commentText.setTextFormat(commentFormatter);
			this.stage.addChild(commentText);
			commentText.x = GOOD_BAD_WIDTH;
			commentText.y = VERTICAL_GUTTER + 10;
			this.width = HORIZONTAL_GUTTER + GOOD_BAD_WIDTH + commentText.textWidth + HORIZONTAL_GUTTER;
			
			var windowHeight:int = VERTICAL_GUTTER + commentText.textHeight + VERTICAL_GUTTER;
			windowHeight = (windowHeight > MAX_HEIGHT) ? MAX_HEIGHT : (windowHeight < MIN_HEIGHT) ? MIN_HEIGHT : windowHeight ;
			this.height = windowHeight;
		}
		
		private function clickHandler(event:MouseEvent, link:String = null):void
		{
			// Ctr+クリックの場合で、かつTwitterのつぶやきの場合はデフォルトブラウザで開く。
			if (event.ctrlKey && link != null)
			{
				try
				{
					navigateToURL(new URLRequest(link), "_blank");
				}
				catch (e:Error)
				{
					// Openに失敗した場合は、エラーを吐いてUI上は処理を実行する。
					logger.error(e.getStackTrace());
				}
			}
			close();
		}
		
		/**
		 * 表示してから一定時間後にクローズする
		 *
		 * @param event
		 */
		public function lifeTick(event:Event):void
		{
			this.timeToLive--;
			if (this.timeToLive < 1)
			{
				close();
			}
		}
		
		/**
		 * 通知ウィンドウを閉じる
		 */
		public override function close():void
		{
			this.manager.removeEventListener(NotificationManager.LIFE_TICK_EVENT, this.lifeTick, false);
			super.close();
		}
		
		/**
		 * 通知ウィンドウの背景を描画する
		 * @param notifyType good/bad
		 * @see http://d.hatena.ne.jp/nitoyon/20070801/as3_iphone_button テック煮さんに感謝
		 */
		private function drawBackground(notifyType:String):void
		{
			var baseColor:uint = (notifyType == NotificationManager.NOTIFY_GOOD) ? GOOD_COLOR : BAD_COLOR;
			
			var background:Sprite = new Sprite();
			var matrix:Matrix = new Matrix();
			matrix.createGradientBox(this.width, this.height, Math.PI / 2);
			
			var base:Shape = new Shape();
			base.graphics.beginFill(baseColor, 0.75);
			base.graphics.drawRoundRect(0, 0, this.width, this.height, ROUND, ROUND);
			background.addChild(base);
			
			var border:Shape = new Shape();
			border.graphics.lineStyle(1, 0xffffff, 1);
			border.graphics.lineGradientStyle("linear", [0xffffff, 0xffffff, 0xffffff], [1, 0.3, 1], [0, 128, 255], matrix);
			border.graphics.drawRoundRect(1, 1, this.width - 2, this.height - 2, ROUND, ROUND);
			border.blendMode = BlendMode.OVERLAY;
			background.addChild(border);
			
			var glowTop:Shape = new Shape();
			glowTop.graphics.beginGradientFill("linear", [0xffffff, 0xffffff], [1, 0.2], [0, 128], matrix);
			glowTop.graphics.drawEllipse(-this.width / 2, -this.height / 2, this.width * 2, this.height);
			glowTop.blendMode = BlendMode.OVERLAY;
			background.addChild(glowTop);
			
			var mask:Shape = new Shape();
			mask.graphics.beginFill(0);
			mask.graphics.drawRoundRect(0, 0, this.width, this.height, ROUND, ROUND);
			background.addChild(mask);
			glowTop.mask = mask;
			
			var glowBottom:Shape = new Shape();
			glowBottom.graphics.beginGradientFill("linear", [0xffffff, 0xffffff], [0, 1], [224, 255], matrix);
			glowBottom.graphics.drawRoundRect(0, 0, this.width, this.height, ROUND, ROUND);
			glowBottom.blendMode = BlendMode.OVERLAY;
			background.addChild(glowBottom);
			
			var filter:DropShadowFilter = new DropShadowFilter(2, 90, 0x000000, 0.7);
			base.filters = [filter];
			
			this.stage.addChildAt(background, 0);
		}
		
		private function getIcon(IconClass:Class):Sprite
		{
			var image:Sprite = new Sprite();
			var bitmap:Bitmap = new IconClass();
			bitmap.width = ICON_SIZE;
			bitmap.height = ICON_SIZE;
			bitmap.smoothing = true;
			image.addChild(bitmap);
			return image;
		}
	}
}